package edu.centenary.centenaryController;
import java.util.*;
import java.io.*;

public class Kmeans{

	//datamembers
	private static int k = 0;
	private static ArrayList<BodyPart> bodyParts = new ArrayList<BodyPart>();
	
	
	//constructor
	public Kmeans(int k, ArrayList<BodyPart> bodyParts){
		this.k = k;
		this.bodyParts = bodyParts;
	}
	//methods
	public static void main(String[] args) throws IOException, FileNotFoundException{
	
		//Read info from text file
		Scanner scan = new Scanner(new File(args[0]));
		while(scan.hasNext()){
			BodyPart bp = new BodyPart(scan.next(),scan.nextDouble(),scan.nextDouble(),scan.nextDouble());
			bodyParts.add(bp);
		}
		//Set k equal to the number of chest body parts
		int ch = 0;
		for(BodyPart bp:bodyParts){
			if(bp.getBodyPart().equals("Chest")){
				ch++;
			}
		}
		
		System.out.println("There are " + ch + " Chests");
		double mindistortion = Double.MAX_VALUE;
		int mink = k;
		for(k=ch; k <= ch;k++){
		
		
		//Select k centers
		BodyPart[] centers = new BodyPart[k];
		int[] r = new int[bodyParts.size()];
		for (int i = 0; i < r.length; i++){
			r[i]= i;
		}
		for (int i = 0; i < k; i++){
			int rand = (int)(Math.random()*(r.length - i))+i;
			int p = r[i];
			r[i] = r[rand];
			r[rand] = p;
			
			//make sure no duplicate rands!
			BodyPart bp = bodyParts.get(r[i]);
			centers[i] = new BodyPart("CENTER",bp.getLocationX(),bp.getLocationY(),bp.getLocationZ());
		}
		
		boolean changed = true;
		
		while(changed){
			//System.out.println("In while loop");
			changed = false;
			//Group points based on proximity to centers by min distance
			int j = 0;
			for(BodyPart bp: bodyParts){
				double minimum = bp.distance(centers[0]);
				//Crisis Averted!
				int c = bp.getCenter();
				
				//For each datapoint, find the closest center
				for(int i = 0; i < k; i++){
					//System.out.println("For loop.  i is " + i);
					if(bp.distance(centers[i]) < minimum){
						minimum = bp.distance(centers[i]);
						//System.out.println("Minimum is:"+minimum +" i is " + i);
						bp.setCenter(i);
						c = bp.getCenter();
					}
				}
				
				bp.setGroup(c);
				j++;
				//System.out.println("Bodypart " + j + " is part of group " + c);
			}
		//Calculate center using new points in group
			for(int i = 0; i < k; i++){
				centers[i] = new BodyPart("CENTER",0,0,0);				
			}
			int[] members = new int[k];
			for(BodyPart bp: bodyParts){
				int group = bp.getGroup();
				centers[group].setLocationX(centers[group].getLocationX() + bp.getLocationX());
				centers[group].setLocationY(centers[group].getLocationY() + bp.getLocationY());
				centers[group].setLocationZ(centers[group].getLocationZ() + bp.getLocationZ());
				//System.out.println(centers[group]);
				members[group]+= 1;
				
			}
			for(int i = 0; i < k; i++){
				centers[i].setLocationX(centers[i].getLocationX() / members[i]);
				centers[i].setLocationY(centers[i].getLocationY() / members[i]);
				centers[i].setLocationZ(centers[i].getLocationZ() / members[i]); 
			}
			int i = 0;
			for(BodyPart bp: bodyParts){
				
				//System.out.println("Checking dirty for: " +i);
				if(bp.getDirty() == true){
					//System.out.println(i + " is dirty");
					changed = true;
					bp.setDirty(false);
				}
			i++;
			}
		}
		//System.out.println("Whoohoo! Loop is gone");
		double distortion = 0;
		for(BodyPart bp: bodyParts){
			distortion+= Math.pow(bp.distance(centers[bp.getGroup()]) / bodyParts.size(),2);
		}
		if(distortion <= mindistortion){
				mindistortion = distortion;
				mink = k;
		}
		//Tell user what groups are
		int ik = 0;
		for(BodyPart bp: bodyParts){
			System.out.println("Bodypart "+ik+" is part of group "+bp.getGroup());
			ik++;
		}
		for(int j = 0; j < k; j++){
			//System.out.println(centers[j]);
		}
		System.out.println("Distortion for "+k+" is "+ distortion);
		}
		System.out.println("Minimum Distortion is " + mindistortion + " for k " + mink);
	}
	
}